/*
 * Copyright 2010 Christoph Widulle (christoph.widulle@googlemail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */



package com.android1.amarena2d.engine;

import com.android1.amarena2d.actions.base.Action;
import com.android1.amarena2d.nodes.behavior.ActionTarget;
import com.android1.amarena2d.commons.collections.FixedSizeMap;

//todo what happens on scene changes ?
//user should handle by himself on onExit and call dispose of all elements.

/**
 * @author Christoph Widulle
 */
public class ActionManager extends EngineObject {

    private final FixedSizeMap<ActionTarget, TargetActionsStore> targets;

    public ActionManager() {
        targets = new FixedSizeMap<ActionTarget, TargetActionsStore>(engine.getConfig().get(Config.ACTIONS_MAX_TARGETS));
    }

    public void run(ActionTarget target, Action action) {
        TargetActionsStore a = findTargetActions(target);
        a.run(action);
    }

    public void pauseAllActions(ActionTarget target) {
        TargetActionsStore a = findTargetActions(target);
        a.pause();
    }

    public void resumeAllActions(ActionTarget target) {
        TargetActionsStore a = findTargetActions(target);
        a.resume();
    }

    public void run(Action action, ActionTarget target, boolean paused) {
        assert action != null : "Argument action must be non-null";
        assert target != null : "Argument target must be non-null";

        TargetActionsStore a = findTargetActions(target);
        if (paused)
            a.pause();
        a.run(action);
    }

    public TargetActionsStore register(ActionTarget target) {
        TargetActionsStore a = findTargetActions(target);
        if (!target.isActive())
            a.pause();
        return a;
    }

    public void stopAllActions(ActionTarget target) {
        TargetActionsStore targetactions = findTargetActions(target);
        targetactions.stopAll();
    }

    public void stop(ActionTarget target, Action action) {
        TargetActionsStore targetactions = findTargetActions(target);
        targetactions.stop(action);
    }


    public boolean hasTargetActionsStore(ActionTarget actionTarget) {
        TargetActionsStore targetActionsStore = targets.get(actionTarget);
        return (targetActionsStore != null);
    }

    private TargetActionsStore findTargetActions(ActionTarget actionTarget) {
        TargetActionsStore targetActionsStore = targets.get(actionTarget);
        if (targetActionsStore == null) {
            targetActionsStore = new TargetActionsStore(actionTarget);
            targets.put(actionTarget, targetActionsStore);
        }
        return targetActionsStore;
    }

    public void tick(float d) {

        int size = targets.getSize();
        if (size > 0) {
            //not convenient but fast and allocation free;
            int count = 0;
            int i = 0;

            while (count != size) {

                final TargetActionsStore targetActionsStore = targets.getValue(i);
                i++;
                if (targetActionsStore != null) {
                    count++;
                    if (!targetActionsStore.paused) {

                        targetActionsStore.actions.applyChanges();
                        final int s = targetActionsStore.actions.getCount();

                        for (int j = 0; j < s; j++) {
                            final Action action = targetActionsStore.actions.get(j);

                            if (action != null) {
                                if (action.isDone()) {
                                    targetActionsStore.stop(action);
                                    if (AmarenaEngine.DEBUG)
                                        engine.log("ActionManager", "Action finished and removed: " + action);
                                } else if (action.isRunning())
                                    action.tick(d);

                            }
                        }
                    }
                }
            }
        }
    }
}
